package com.yc.config;

import com.yc.filter.JWTFilter;
import com.yc.service.UserBizImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author zwei
 * @create 2024-09-04 17:13
 */
@Configuration
public class WebSecurityConfig {

    public static void main(String[] args) {
         BCryptPasswordEncoder bc= new BCryptPasswordEncoder();
         System.out.println(bc.encode("chxchx"));
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(); // 密码加密器
    }
    //ResuserBizImpl时实现了UserDetailsService接口的类 是spring Security提供的一个接口 用于从数据库中获取用户信息
    private UserBizImpl userBizImpl;
    @Autowired
    public void setResuserBizImpl(UserBizImpl userBizImpl){
        this.userBizImpl=userBizImpl;
    }
    private JWTFilter jwtFilter;
    @Autowired
    public void setJwtFilter(JWTFilter jwtFilter){
        this.jwtFilter=jwtFilter;
    }
    @Bean       //认证服务提供器  组装组件
    public AuthenticationProvider authenticationProvider(){
        DaoAuthenticationProvider provider=new DaoAuthenticationProvider();
        provider.setPasswordEncoder(passwordEncoder()); //密码加密
        provider.setUserDetailsService(userBizImpl); //组装一个业务  实现UserDetailsService接口的类
        return provider;
    }
    @Bean   //认证管理器
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
        return configuration.getAuthenticationManager();
    }
    //security的配置  通过过滤器实现  组件的配置
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.formLogin(AbstractHttpConfigurer::disable) //取消默认登录页面的使用 因为是前后端分离的项目
                .logout(AbstractHttpConfigurer::disable)    //取消默认退出页面的使用
                .authenticationProvider(authenticationProvider())   //将自己配置的PasswordEncoder放入SecurityFilterChain中
                .csrf(AbstractHttpConfigurer::disable)  //禁用csrf保护，前后端分离不需要
                .sessionManagement(session->session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) //禁用session因为我们已经使用了JWT
                .httpBasic(AbstractHttpConfigurer::disable) //禁用httpBasic，因为我们传输数据用的post 而且请求体是JSON
                .authorizeHttpRequests(request->
                        request.requestMatchers(HttpMethod.POST,"/ordersecurity/login","/ordersecurity/register","ordersecurity/logout").permitAll()
                                .requestMatchers(HttpMethod.GET,"/ordersecurity/captcha").permitAll()
                                .anyRequest().authenticated()   //开放四个接口  一个注册，一个登录，一个退出，一个验证码，其余均要身份认证
                        )
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        //将用授权用到的JWT校验过滤器添加到SecurityFilterChain中 并放在UsernamePasswordAuthenticationFilter之前
        return httpSecurity.build();
    }
}
